package loaders;

import foxtrot.Task;
import gui.BetterFlowLayout;
import gui.custom.AAButton;
import gui.custom.AALabel;
import gui.custom.ClickableLabel;
import gui.custom.RatingPanel;
import gui.custom.SelectedSwatchPanel;
import gui.custom.SwatchPanel;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.net.URL;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

import actions.GetDetailedTheme;
import actions.GetNextThemes;
import actions.GetPreviousThemes;
import actions.HighestRated;
import actions.MostPopular;
import actions.RandomThemes;
import actions.RecentThemes;
import actions.SearchAction;
import backend.ThemeManager;
import backend.rss.ItemsContainer;
import backend.rss.items.CommentItem;
import backend.rss.items.DetailedThemeItem;
import backend.rss.items.TagItem;
import backend.rss.items.ThemeItem;

public class ThemeViewer extends JApplet
{
	private static final DateFormat DATEFORMAT = new SimpleDateFormat("dd, MMM yyyy' at 'HH:mm:ss");
	
	public static final Font TITLEFONT = new Font("Verdana", Font.BOLD, 18);
	public static final Font BUTTONFONT = new Font("Verdana", Font.BOLD, 12);
	
	private ThemeManager themeManager;
	private JPanel detailsPanel;
	private JPanel browsePanel;
	private JPanel selectedSwatchPanel;

	private JPanel progressPanel;
	private JProgressBar progressBar;
	
	private JLabel browseLabel;
	private JLabel titleLabel;
	private JLabel searchLabel;
	
	private JTextField searchField;

	public void init()
	{
		loadAppletParameters();

		UIManager.put("Panel.background", Color.black);
		UIManager.put("Label.foreground", Color.white);
		//Execute a job on the event-dispatching thread:
		//creating this applet's GUI.
		try
		{
			SwingUtilities.invokeAndWait(new Runnable()
			{
				public void run()
				{
					createGUI();
				}
			});
		}
		catch (Exception e)
		{
			System.err.println("createGUI didn't successfully complete");
		}
	}
	
	private void loadAppletParameters()
	{
		themeManager = new ThemeManager(this);
	}
	
	private void createGUI()
	{
		Container pane = getContentPane();
		setSize(1000, 650);
		setPreferredSize(new Dimension(1000,650));

		browseLabel = new AALabel("Browse");
		titleLabel 	= new AALabel("Title");
		searchLabel	= new AALabel("Search");
		
		browseLabel.setFont(TITLEFONT);
		titleLabel.setFont(TITLEFONT);
		searchLabel.setFont(TITLEFONT);		
		
				
		GridBagLayout gbl = new GridBagLayout();
		GridBagConstraints gbc = new GridBagConstraints();		
		
		JPanel backgroundPanel = new JPanel(new BorderLayout());
		backgroundPanel.setSize(getSize());
		backgroundPanel.setPreferredSize(getSize());
		
		JPanel bottomPanel	   = new JPanel(gbl);
		bottomPanel.setSize(backgroundPanel.getWidth(), 470);
		bottomPanel.setPreferredSize(new Dimension(backgroundPanel.getWidth(), 470));
		
		selectedSwatchPanel = new JPanel(new BorderLayout(0,0));
		selectedSwatchPanel.setSize(getWidth(), 180);
		selectedSwatchPanel.setPreferredSize(new Dimension(getWidth(), 180));
		
		backgroundPanel.add(selectedSwatchPanel, BorderLayout.NORTH);
		backgroundPanel.add(bottomPanel, BorderLayout.SOUTH);	
		
		int panelWidth = 200;

		detailsPanel = new JPanel(new BorderLayout());
		
		browsePanel = new JPanel(new BorderLayout());
		JScrollPane scroller = new JScrollPane(browsePanel);
		scroller.setSize(panelWidth, bottomPanel.getHeight());
		scroller.setPreferredSize(new Dimension(panelWidth, bottomPanel.getHeight()));		

		JPanel searchPanel = new JPanel(new BorderLayout());
		searchPanel.setSize(panelWidth, bottomPanel.getHeight());
		searchPanel.setPreferredSize(new Dimension(panelWidth, bottomPanel.getHeight()));
		
		progressPanel 	= new JPanel(new BetterFlowLayout());
		progressBar 	= new JProgressBar(0, 100);
		progressBar.setSize(50, 5);
		progressBar.setIndeterminate(true);
		progressPanel.setSize(55, 5);
		progressPanel.add(progressBar);
		
		detailsPanel.setSize(getWidth() - panelWidth * 2, bottomPanel.getHeight());
		detailsPanel.setPreferredSize(new Dimension(getWidth() - panelWidth * 2, bottomPanel.getHeight()));

		
		gbc.gridy = 0;		
		gbc.gridheight = 1;
		gbc.weighty=1;
		gbc.weightx=1;
		
		gbc.anchor = GridBagConstraints.WEST;
		gbc.fill = GridBagConstraints.NONE;

		gbc.gridx = 0;		
		gbc.gridwidth = 1;
		gbl.setConstraints(detailsPanel, gbc);			
		
		gbc.gridwidth = 1;
		gbc.gridx = 1;
		gbl.setConstraints(scroller, gbc);

		gbc.gridx = 2;
		gbl.setConstraints(searchPanel, gbc);



		//selectedSwatchPanel.setBackground(Color.BLACK);
		//browsePanel.setBackground(Color.GREEN);
		//searchPanel.setBackground(Color.red);
		//detailsPanel.setBackground(Color.BLUE);
		
		bottomPanel.add(detailsPanel);
		bottomPanel.add(scroller);
		bottomPanel.add(searchPanel);
		
		browsePanel.add(browseLabel, BorderLayout.NORTH);	
		detailsPanel.add(titleLabel, BorderLayout.NORTH);
		
		initSearchPanel(searchPanel);

		pane.add(backgroundPanel);
	
		hideProgressBar();
	}
	
	private void initToolBarPalette(JPanel toolbar)
	{
		JLabel recentThemes 	= new ClickableLabel("Newest", BUTTONFONT);
		JLabel mostPopular 	= new ClickableLabel("Most Popular", BUTTONFONT);
		JLabel highestRated	= new ClickableLabel("Highest Rated", BUTTONFONT);
		JLabel random			= new ClickableLabel("Random", BUTTONFONT);

		recentThemes.addMouseListener(new RecentThemes(themeManager));
		mostPopular.addMouseListener(new MostPopular(themeManager));
		highestRated.addMouseListener(new HighestRated(themeManager));
		random.addMouseListener(new RandomThemes(themeManager));
		
		GridBagConstraints gbc 	= new GridBagConstraints();
		
		addToolBarButton(recentThemes,
						 toolbar,
						 gbc,
						 0);
		
		addToolBarButton(mostPopular,
						 toolbar,
						 gbc,
						 1);
		
		addToolBarButton(highestRated,
				 		 toolbar,
				 		 gbc,
				 		 2);

		addToolBarButton(random,
						 toolbar,
						 gbc,
						 3);
		
	}
	
	private void addToolBarButton(JLabel label, 
								  JPanel toolbar, 
								  GridBagConstraints gbc, 
								  int ypos)
	{
		GridBagLayout gbl	   	= (GridBagLayout) toolbar.getLayout();
		Dimension dimension		= new Dimension(100, 20);
		Box.Filler filler 		= new Box.Filler(dimension, dimension, dimension);
		
		gbc.fill = GridBagConstraints.NONE;
		gbc.anchor = GridBagConstraints.WEST;
		gbc.gridx = 0;
		gbc.gridy = ypos;
		gbl.setConstraints(label, gbc);

		gbc.gridx = 1;
		gbc.gridy = ypos;
		gbc.fill = GridBagConstraints.BOTH;
		gbl.setConstraints(filler, gbc);
		
		toolbar.add(label);
		toolbar.add(filler);
	}
	
	private void initSearchPanel(JPanel searchPanel)
	{
		GridBagConstraints gbc = new GridBagConstraints();
		//gbl = (GridBagLayout) searchPanel.getLayout();
		JPanel tempPanel = new JPanel(new GridBagLayout());
		GridBagLayout gbl = (GridBagLayout) tempPanel.getLayout();
		tempPanel.setSize(searchPanel.getSize());
		

		/*
		JToolBar toolbar = new JToolBar("Themes", JToolBar.VERTICAL);
		toolbar.add(new RecentThemes(themeManager));
		toolbar.add(new MostPopular(themeManager));
		toolbar.add(new HighestRated(themeManager));
		toolbar.add(new RandomThemes(themeManager));
		*/
		JPanel toolbar = new JPanel(new GridBagLayout()); 
		initToolBarPalette(toolbar);
		
		searchField = new JTextField();
		
		gbc.fill = GridBagConstraints.BOTH;
		gbc.gridx = 0;
		gbc.gridy = 0;
		gbc.weightx = 1;
		gbc.gridwidth = GridBagConstraints.REMAINDER;
		//gbc.gridheight = 1;
		gbl.setConstraints(searchLabel, gbc);
		
		searchField.setPreferredSize(new Dimension(100, 20));
		searchField.setSize(100,20);
		
		gbc.weightx = 1;
		gbc.gridy = 1;
		gbc.gridwidth = 1;
		gbl.setConstraints(searchField, gbc);
		
		JButton searchButton = new AAButton("Search");
		searchButton.setPreferredSize(new Dimension(30, 20));
		searchButton.setSize(30, 20);
		gbc.gridx = 1;
		gbc.gridwidth = GridBagConstraints.REMAINDER;
		gbl.setConstraints(searchButton, gbc);
		
		gbc.gridx = 0;
		gbc.gridy = 2;
		gbc.gridwidth = 2;
		gbc.fill = GridBagConstraints.BOTH;
		gbl.setConstraints(progressPanel, gbc);
		
		gbc.gridx = 0;
		gbc.gridy = 3;
		gbc.gridwidth = 2;
		gbc.fill = GridBagConstraints.BOTH;
		gbl.setConstraints(toolbar, gbc);


		tempPanel.add(searchLabel);
		tempPanel.add(searchField);
		tempPanel.add(searchButton);
		tempPanel.add(progressPanel);
		tempPanel.add(toolbar);
		
		searchPanel.add(tempPanel, BorderLayout.NORTH);	
		

		searchButton.addActionListener(new SearchAction(themeManager, searchField));
	}
	
	private void initBrowsePanel()
	{
		browsePanel.removeAll();
		browsePanel.add(browseLabel, BorderLayout.NORTH);
	}
	
	public void hideProgressBar()
	{
		progressBar.setValue(0);
		progressBar.setVisible(false);
	}
	
	public void displayProgressBar()
	{
		progressBar.setVisible(true);
		progressBar.setValue(10);
	}
		
	public void showThemeDetails(final DetailedThemeItem item)
	{
		detailsPanel.removeAll();
		selectedSwatchPanel.removeAll();
		
		titleLabel.setText(item.getTitle());
		detailsPanel.add(titleLabel, BorderLayout.NORTH);
		
		GridBagLayout gbl = new GridBagLayout();
		GridBagConstraints gbc = new GridBagConstraints();
		
		//JPanel details = new JPanel(new GridLayout(5, 3, 0, 0));
		JPanel details = new JPanel(gbl);
		details.setBorder(BorderFactory.createMatteBorder(10,10,50,10, Color.black));
		
		JLabel createdDate 		= new AALabel("Created"); 
		JLabel cDateColon		= new AALabel(":");
		JLabel createdDateValue	= new AALabel(DATEFORMAT.format(item.getDateCreated()));
		JLabel editedDate 		= new AALabel("Last Edited");
		JLabel eDateColon		= new AALabel(":");		
		JLabel editedDateValue 	= new AALabel(DATEFORMAT.format(item.getDateEdited()));
		JLabel rated			= new AALabel("Rated");
		JLabel ratedColon		= new AALabel(":");				
		JLabel ratedValue		= new AALabel(item.getRatingFractional()+" ("+item.getVotes()+" votes)");
		JLabel favourited		= new AALabel("Favourited By");
		JLabel fColon			= new AALabel(":");
		JLabel favouritedValue	= new AALabel(item.getNumFavourites()+" members");		
		JLabel downloaded		= new AALabel("Downloaded");
		JLabel dColon			= new AALabel(":");				
		JLabel downloadedValue	= new AALabel(item.getDownloads()+" times");
		JLabel tags				= new AALabel("Tags");
		JLabel tagsColon		= new AALabel(":");		
		JPanel tagsContainer 	= new JPanel(new BetterFlowLayout(FlowLayout.LEFT, 3, 0));

		Dimension tagsDimension	= new Dimension(150, 100);
		tagsContainer.setSize(tagsDimension);
		tagsContainer.setMaximumSize(tagsDimension);
		tagsContainer.setPreferredSize(tagsDimension);
		tagsContainer.setMinimumSize(tagsDimension);
		

		for (TagItem t : item.getTags())
		{
			final ClickableLabel tag = new ClickableLabel(t.getLabel());
			tag.addMouseListener(new Task()
			{
				@Override
				public Object run() throws Exception
				{
					themeManager.tagSearch(tag.getText());
					return null;
				}
			});

			tagsContainer.add(tag);
		}
	
		createdDateValue.setHorizontalAlignment(JLabel.RIGHT);
		editedDateValue.setHorizontalAlignment(JLabel.RIGHT);
		ratedValue.setHorizontalAlignment(JLabel.RIGHT);
		downloadedValue.setHorizontalAlignment(JLabel.RIGHT);

		Dimension dimension = new Dimension(300, 10);
		Box.Filler filler = new Box.Filler(dimension, dimension, dimension);
		
		setDetailsPanelElementConstraints(gbl, gbc, 0, 0, createdDate, cDateColon, createdDateValue, filler);
		setDetailsPanelElementConstraints(gbl, gbc, 0, 1, editedDate, eDateColon, editedDateValue, filler);
		setDetailsPanelElementConstraints(gbl, gbc, 0, 2, rated, ratedColon, ratedValue, filler);
		setDetailsPanelElementConstraints(gbl, gbc, 0, 3, favourited, fColon, favouritedValue, filler);
		setDetailsPanelElementConstraints(gbl, gbc, 0, 4, downloaded, dColon, downloadedValue, filler);
		
		
		
		gbc.gridx = 0;
		gbc.gridy = 5;
		gbc.fill = GridBagConstraints.NONE;
		gbc.anchor = GridBagConstraints.WEST;		
		gbl.setConstraints(tags, gbc);
		
		gbc.gridx = 0;
		gbc.gridwidth = 3;
		gbc.gridy = 6;
		gbc.weightx = 1;
		gbc.ipady = 1;
		gbc.fill = GridBagConstraints.HORIZONTAL;
		gbc.anchor = GridBagConstraints.WEST;		
		gbl.setConstraints(tagsContainer, gbc);
		
		/**
		 * Create comments panel
		 */
		JScrollPane commentsPane = createDetailsPanelCommentPanel(new Dimension(detailsPanel.getSize().width - 40, 
																			 	300),
																   item.getComments());
		
		
		
		gbc.gridx = 0;
		gbc.gridwidth = 3;
		gbc.gridheight = 1;
		gbc.gridy = 7;
		gbc.ipady = 180;
		gbc.fill = GridBagConstraints.BOTH;
		gbl.setConstraints(commentsPane, gbc);
		
		
		details.add(createdDate);
		//details.add(cDateColon);
		details.add(createdDateValue);
		details.add(filler);
		
		details.add(editedDate);
		//details.add(eDateColon);
		details.add(editedDateValue);
		
		details.add(rated);
		//details.add(ratedColon);
		details.add(ratedValue);
		
		details.add(favourited);
		details.add(favouritedValue);
		
		details.add(downloaded);
		//details.add(dColon);
		details.add(downloadedValue);
		
		details.add(tags);
		//details.add(tagsColon);
		details.add(tagsContainer);
		
		details.add(commentsPane);
		
		detailsPanel.add(details, BorderLayout.CENTER);
		
		//detailsPanel.add(commentsPane, BorderLayout.SOUTH);
		
		Dimension bigSwatchSize = selectedSwatchPanel.getSize();
		
		JPanel bigSwatch = new SelectedSwatchPanel(item, bigSwatchSize);
		
		selectedSwatchPanel.add(bigSwatch, BorderLayout.CENTER);
	
		selectedSwatchPanel.repaint();
		this.repaint();
		validate();
	}
	
	private JScrollPane createDetailsPanelCommentPanel(Dimension size, List<CommentItem> comments)
	{
		GridBagLayout gbl 		= new GridBagLayout();
		GridBagConstraints gbc	= new GridBagConstraints();
		JPanel commentPanel 	= new JPanel(gbl);
		JScrollPane scroller	= new JScrollPane(commentPanel);
		scroller.setPreferredSize(size);
		scroller.setSize(size);
		
		Dimension dimension = new Dimension(size.width, 5);

		
		int y = 0;
		for (final CommentItem comment : comments)
		{
			//create a search task for the user
			Task task = new Task()
			{
				@Override
				public Object run() throws Exception
				{
					searchField.setText(comment.getAuthor().getName());
					themeManager.defaultSearch(comment.getAuthor().getName());
					return null;
				}
				
			};
			
			URL avatarURL			= comment.getAuthor().getImageURL();
			ClickableLabel avatar	= new ClickableLabel();
			if (avatarURL != null) 
			{
				avatar = new ClickableLabel(new ImageIcon(avatarURL));
				avatar.setBorder(BorderFactory.createMatteBorder(1,1,1,1, Color.BLACK));
			}
			
			avatar.addMouseListener(task);
						
			String commentHeader	= "Posted on " + DATEFORMAT.format(comment.getPostedDate())+" by "+
								  	  comment.getAuthor().getName();
			
			JLabel header			= new AALabel(commentHeader, size.width);
			//set title colour
			header.setForeground(Color.GRAY);
			
			//html tag to make it wrap
			JLabel commentText		= new AALabel("<html>"+comment.getStrippedComment()+"</html>", 
												  size.width);
			Box.Filler filler = new Box.Filler(dimension, dimension, dimension);		
			gbc.gridy = y;
			gbc.gridx = 0;
			gbc.gridwidth = 1;
			gbc.gridheight = 2;
			gbc.anchor = GridBagConstraints.WEST;
			gbl.setConstraints(avatar, gbc);
			
			gbc.gridx = 1;
			gbc.gridy = y;
			gbc.gridheight = 1;
			
			gbl.setConstraints(header, gbc);
			
			gbc.gridx = 1;
			gbc.gridy = y + 1;
			gbc.fill = GridBagConstraints.REMAINDER;
			gbl.setConstraints(commentText, gbc);
			
			gbc.gridy = y + 2;
			gbc.gridx = 0;
			gbc.gridwidth = 2;
			gbc.fill = GridBagConstraints.HORIZONTAL;
			gbl.setConstraints(filler, gbc);
			
			commentPanel.add(avatar);
			commentPanel.add(header);
			commentPanel.add(commentText);
			commentPanel.add(filler);
			
			y+=3;
		}
		
		return scroller;
	}
	
	private void setDetailsPanelElementConstraints(GridBagLayout gbl, 
												   GridBagConstraints gbc, 
												   int startX,
												   int rowNum,
												   JLabel fieldLabel,
												   JLabel fieldColon, //not used
												   JLabel fieldValue,
												   Box.Filler filler)
	{
		gbc.gridy = rowNum;
		
		gbc.gridwidth = 1;
		gbc.gridheight = 1;
		gbc.weightx = 1;
		gbc.anchor = GridBagConstraints.WEST;
		gbc.fill = GridBagConstraints.NONE;
		
		gbc.gridx = startX + 0;

		gbl.setConstraints(fieldLabel, gbc);
		gbc.fill = GridBagConstraints.NONE;
		gbc.anchor = GridBagConstraints.EAST;		
		gbc.gridx = startX + 1;
		gbl.setConstraints(fieldValue, gbc);
		
		gbc.gridx = startX + 2;
		gbc.fill = GridBagConstraints.REMAINDER;
		gbl.setConstraints(filler, gbc);
	}
	
	public void updateBrowsePanel(final ItemsContainer itemsContainer) 
	{
		initBrowsePanel();
			
		GridBagLayout gbl 		= new GridBagLayout();
		GridBagConstraints gbc 	= new GridBagConstraints();
		JPanel themePanel		= new JPanel(gbl);
		themePanel.setSize(browsePanel.getPreferredSize());
		themePanel.setSize(browsePanel.getSize());
		int y=0;
		
		for (final ThemeItem item : itemsContainer.formatForViewer().keySet())
		{
			
			ClickableLabel themeTitle = new ClickableLabel(item.getShortTitle());
			
			final GetDetailedTheme detailedThemeAction = new GetDetailedTheme(themeManager, item.getId());
			themeTitle.addMouseListener(detailedThemeAction);

			JPanel themeImage = new SwatchPanel(themeTitle, item, new Dimension(80, 15), detailedThemeAction);
			JPanel ratingPanel = new RatingPanel(item);
		
			
			gbc.gridwidth = 1;
			gbc.gridheight = 1;
			gbc.weightx = 1;
			gbc.anchor = GridBagConstraints.WEST;
			gbc.fill = GridBagConstraints.NONE;
			
			gbc.gridx = 0;
			gbc.gridy = y++;
			gbl.setConstraints(themeTitle, gbc);
			
			gbc.gridx = 1;
			gbc.gridwidth = GridBagConstraints.REMAINDER;
			gbc.anchor = GridBagConstraints.EAST;
			gbl.setConstraints(ratingPanel, gbc);
			
			gbc.gridx = 0;
			gbc.gridy = y++;
			gbc.gridwidth = GridBagConstraints.REMAINDER;
			gbc.anchor = GridBagConstraints.WEST;
			gbl.setConstraints(themeImage, gbc);
			
			Dimension dimension = new Dimension(20, 10);
			Box.Filler filler = new Box.Filler(dimension, dimension, dimension);
			gbc.gridy = y++;
			gbl.setConstraints(filler, gbc);
			
			themePanel.add(themeTitle);
			themePanel.add(ratingPanel);
			themePanel.add(themeImage);
			
			themePanel.add(filler);
		}
		
		//themePanel.setBackground(Color.BLACK);
		browsePanel.add(themePanel, BorderLayout.CENTER);
		browsePanel.add(addBrowsePaging(itemsContainer), BorderLayout.SOUTH);
		repaint();
		validate();
	}
	
	private JPanel addBrowsePaging(final ItemsContainer itemsContainer)
	{
		JPanel pagingPanel = new JPanel(new BetterFlowLayout());
		pagingPanel.setSize(browsePanel.getSize().width, 30);
		pagingPanel.setPreferredSize(new Dimension(browsePanel.getPreferredSize().width, 30));
		
		Dimension buttonDimension 	= new Dimension(20, 20);
		
		JButton previousButton 		= new AAButton("<");
		previousButton.setSize(buttonDimension);
		previousButton.setPreferredSize(buttonDimension);
		previousButton.addActionListener(new GetPreviousThemes(themeManager));		
		
		JButton nextButton			= new AAButton(">");
		nextButton.setSize(buttonDimension);
		nextButton.setPreferredSize(buttonDimension);
		nextButton.addActionListener(new GetNextThemes(themeManager));
		
		int start 	= itemsContainer.getStartIndex() + 1;
		int end 	= start + itemsContainer.getItemsPerPage() - 1;
		
		JLabel position				= new AALabel("(" + start + " - " + 
												  end +
												  " of " + 
												  itemsContainer.getRecordCount()+")");
		
		
		pagingPanel.add(position);
		if (itemsContainer.getStartIndex() > 0) pagingPanel.add(previousButton);
		pagingPanel.add(nextButton);
		
		return pagingPanel;
	}
}